using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using MediaBridge;
using DirectShowLib;
using System.Runtime.InteropServices.ComTypes;
using System.Runtime.InteropServices;

namespace MediaBridgeDemo
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>

    public partial class Window1 : System.Windows.Window
    {

        IBaseFilter filter;
        IFilterGraph graph;
        IGraphBuilder graphBuilder;
        ICaptureGraphBuilder2 captureGB;

        public Window1()
        {
            InitializeComponent();
            
            //btnStart.Click += new RoutedEventHandler(btnStart_Click);           
        }

        void btnStart_Click(object sender, RoutedEventArgs e)
        {
            string url = "MediaBridge://MyDataString";            

            MediaBridge.MediaBridgeManager.RegisterCallback(url, BridgeCallback);

            BridgedElement.Source = new Uri(url);
            
            BridgedElement.Play();
        }

        private void BridgeCallback(MediaBridgeGraphInfo GraphInfo)
        {
            int hr = 0;

            //Find a capture filter
            filter = FindCaptureDevice();

            //Convert pointer of filter graph to an object we can use
            graph = (IFilterGraph)Marshal.GetObjectForIUnknown(GraphInfo.FilterGraph);

            graphBuilder = (IGraphBuilder)graph;

            captureGB =  (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
            
            hr = captureGB.SetFiltergraph(graphBuilder);
            
            //Add our capture filter to the graph
            hr = graph.AddFilter(filter, "CAPTURE");
           
            IBaseFilter renderer;
            
            //Find WPF renderer.  It's always named the same thing
            hr = graphBuilder.FindFilterByName("Enhanced Video Renderer", out renderer);

            //Render our filters outpin to the renderer
            hr = captureGB.RenderStream(PinCategory.Capture, MediaType.Video, filter, null, renderer);

            DsROTEntry entry = new DsROTEntry(graph);
        }

        /// <summary>
        /// Finds a capture filter.  From DirectShow.net sample
        /// </summary>
        /// <returns></returns>
        public IBaseFilter FindCaptureDevice()
        {
          int hr = 0;

          IEnumMoniker classEnum = null;
          IMoniker[] moniker = new IMoniker[1];

          object source = null;

          // Create the system device enumerator
          ICreateDevEnum devEnum = (ICreateDevEnum) new CreateDevEnum();

          // Create an enumerator for the video capture devices
          hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, out classEnum, 0);
          DsError.ThrowExceptionForHR(hr);

          // The device enumerator is no more needed
          Marshal.ReleaseComObject(devEnum);

          // If there are no enumerators for the requested type, then 
          // CreateClassEnumerator will succeed, but classEnum will be NULL.
          if (classEnum == null)
          {
            throw new ApplicationException("No video capture device was detected.\r\n\r\n" +
                                           "This sample requires a video capture device, such as a USB WebCam,\r\n" +
                                           "to be installed and working properly.  The sample will now close.");
          }

          // Use the first video capture device on the device list.
          // Note that if the Next() call succeeds but there are no monikers,
          // it will return 1 (S_FALSE) (which is not a failure).  Therefore, we
          // check that the return code is 0 (S_OK).

          if (classEnum.Next (moniker.Length, moniker, IntPtr.Zero) == 0)
          {
            // Bind Moniker to a filter object
            Guid iid = typeof(IBaseFilter).GUID;
            moniker[0].BindToObject(null, null, ref iid, out source);
          }
          else
          {
            throw new ApplicationException("Unable to access video capture device!");   
          }

          // Release COM objects
          Marshal.ReleaseComObject(moniker[0]);
          Marshal.ReleaseComObject(classEnum);

          // An exception is thrown if cast fail
          return (IBaseFilter) source;
        }

    }
}